#!/usr/bin/env python3
"""
优化版本的 git_pull_all 主程序
集成所有性能优化功能
"""

import sys
import os
import time
import signal
import argparse
from pathlib import Path
from typing import List, Dict, Any, Optional
import psutil

# 导入优化后的模块
try:
    from models.configuration import Configuration
    from utils.optimized_directory_scanner import OptimizedDirectoryScanner
    from utils.optimized_git_executor import OptimizedGitExecutor, ExecutionResult
    from utils.stream_processor import StreamProcessor, StreamResult, ProgressTracker
    from utils.dynamic_thread_pool import DynamicThreadPoolManager, ThreadPoolConfig
    from utils.result_reporter import ResultReporter
except ImportError as e:
    print(f"错误：无法导入模块: {e}")
    print("请确保所有模块文件都在正确的位置")
    sys.exit(1)


class OptimizedGitPullAll:
    """优化的 Git 批量更新工具"""
    
    def __init__(self):
        """初始化"""
        self.config: Optional[Configuration] = None
        self.scanner: Optional[OptimizedDirectoryScanner] = None
        self.executor: Optional[OptimizedGitExecutor] = None
        self.stream_processor: Optional[StreamProcessor] = None
        self.pool_manager: Optional[DynamicThreadPoolManager] = None
        self.progress_tracker: Optional[ProgressTracker] = None
        self.reporter: Optional[ResultReporter] = None
        
        # 性能监控
        self.start_time = 0
        self.end_time = 0
        self.performance_stats = {}
        
        # 取消标志
        self.cancelled = False
        
        # 设置信号处理
        signal.signal(signal.SIGINT, self._signal_handler)
        signal.signal(signal.SIGTERM, self._signal_handler)
    
    def _signal_handler(self, signum, frame):
        """信号处理器"""
        print(f"\n收到信号 {signum}，正在优雅退出...")
        self.cancelled = True
        self.cleanup()
        sys.exit(1)
    
    def run(self, args):
        """
        运行主程序
        
        Args:
            args: 命令行参数
        """
        self.start_time = time.time()
        
        try:
            # 1. 创建和验证配置
            print("1. 初始化配置...")
            self.config = self._create_config(args)
            if not self.config:
                print("配置创建失败，程序退出")
                return 1
            
            print(f"配置完成: {self.config.get_summary()}")
            
            # 2. 初始化组件
            print("\n2. 初始化组件...")
            if not self._initialize_components():
                print("组件初始化失败，程序退出")
                return 1
            
            # 3. 扫描 Git 仓库
            print(f"\n3. 扫描目录: {self.config.root_directory}")
            git_repos = self._scan_repositories()
            
            if not git_repos:
                print("未找到任何 Git 仓库")
                return 0
            
            print(f"找到 {len(git_repos)} 个 Git 仓库")
            
            # 4. 处理仓库
            print("\n4. 开始处理仓库...")
            self._process_repositories(git_repos)
            
            # 5. 生成报告
            print("\n5. 生成报告...")
            self._generate_report()
            
            # 6. 性能统计
            self.end_time = time.time()
            self._print_performance_stats()
            
            return 0
            
        except Exception as e:
            print(f"程序执行出错: {e}")
            return 1
        
        finally:
            self.cleanup()
    
    def _create_config(self, args) -> Optional[Configuration]:
        """
        创建配置对象
        
        Args:
            args: 命令行参数
            
        Returns:
            Configuration: 配置对象
        """
        try:
            config = Configuration(
                root_directory=args.directory,
                include_patterns=args.include,
                exclude_patterns=args.exclude,
                verbose=args.verbose,
                dry_run=args.dry_run,
                timeout=args.timeout,
                max_workers=args.max_workers
            )
            
            if not config.is_valid:
                print(f"配置错误: {config.error_message}")
                return None
                
            return config
            
        except Exception as e:
            print(f"创建配置时发生错误: {str(e)}")
            return None
    
    def _initialize_components(self) -> bool:
        """
        初始化所有组件
        
        Returns:
            bool: 是否成功初始化
        """
        try:
            # 创建优化的目录扫描器
            self.scanner = OptimizedDirectoryScanner(
                max_depth=10,
                cache_dir="/tmp/git_pull_cache",
                cache_ttl=3600,  # 1小时缓存
                batch_size=100,
                max_workers=self.config.max_workers
            )
            
            # 创建优化的 Git 执行器
            self.executor = OptimizedGitExecutor(
                timeout=self.config.timeout,
                verbose=self.config.verbose,
                max_retries=3,
                retry_delay=1.0,
                max_workers=self.config.max_workers,
                batch_size=10
            )
            
            # 创建动态线程池管理器
            pool_config = ThreadPoolConfig(
                min_workers=2,
                max_workers=self.config.max_workers,
                target_cpu_usage=70.0,
                target_memory_usage=80.0,
                adjustment_interval=5.0
            )
            pool_config.verbose = self.config.verbose
            self.pool_manager = DynamicThreadPoolManager(pool_config)
            self.pool_manager.start()
            
            # 创建流式处理器
            self.stream_processor = StreamProcessor(
                buffer_size=1000,
                batch_size=50,
                flush_interval=1.0
            )
            
            # 设置回调函数
            self.stream_processor.set_result_callback(self._on_result)
            self.stream_processor.set_batch_callback(self._on_batch)
            self.stream_processor.set_error_callback(self._on_error)
            self.stream_processor.start()
            
            # 创建结果报告器
            self.reporter = ResultReporter(verbose=self.config.verbose)
            
            return True
            
        except Exception as e:
            print(f"初始化组件时发生错误: {str(e)}")
            return False
    
    def _scan_repositories(self) -> List[str]:
        """
        扫描 Git 仓库
        
        Returns:
            List[str]: Git 仓库路径列表
        """
        scan_start = time.time()
        
        git_repos = self.scanner.find_git_repositories(
            self.config.root_directory,
            self.config.include_patterns,
            self.config.exclude_patterns
        )
        
        scan_time = time.time() - scan_start
        
        # 记录扫描统计
        scanner_stats = self.scanner.get_stats()
        print(f"扫描统计:")
        print(f"  - 扫描时间: {scan_time:.2f}秒")
        print(f"  - 总目录数: {scanner_stats['total_directories']}")
        print(f"  - 缓存命中: {scanner_stats['cache_hits']}")
        
        return git_repos
    
    def _process_repositories(self, git_repos: List[str]):
        """
        处理 Git 仓库
        
        Args:
            git_repos: Git 仓库列表
        """
        # 创建进度跟踪器
        self.progress_tracker = ProgressTracker(len(git_repos))
        
        # 开始处理
        self.reporter.start_processing(len(git_repos))
        
        # 使用线程池并发处理
        self._process_with_thread_pool(git_repos)
    
    def _process_with_thread_pool(self, git_repos: List[str]):
        """
        使用线程池处理仓库
        
        Args:
            git_repos: Git 仓库列表
        """
        # 提交所有任务
        futures = []
        for repo_path in git_repos:
            if self.cancelled:
                break
                
            future = self.pool_manager.submit_task(
                self._process_single_repository,
                repo_path
            )
            futures.append(future)
        
        # 等待所有任务完成
        for i, future in enumerate(futures, 1):
            if self.cancelled:
                break
                
            try:
                result = future.result(timeout=self.config.timeout + 30)
                
                # 更新进度
                self.progress_tracker.update()
                
                # 打印进度（每10个仓库或最后10个）
                if i % 10 == 0 or i > len(git_repos) - 10:
                    self.progress_tracker.print_progress()
                    
            except Exception as e:
                print(f"处理仓库时出错: {e}")
    
    def _process_single_repository(self, repo_path: str) -> StreamResult:
        """
        处理单个仓库
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            StreamResult: 处理结果
        """
        try:
            # 检查仓库有效性
            if not self.scanner.is_valid_git_repo(repo_path):
                return StreamResult(
                    repo_path=repo_path,
                    status="skipped",
                    error="无效的 Git 仓库"
                )
            
            # 如果是预览模式
            if self.config.dry_run:
                return StreamResult(
                    repo_path=repo_path,
                    status="skipped",
                    error="预览模式，未执行操作"
                )
            
            # 执行 git pull
            execution_result = self.executor.pull_repository(repo_path)
            
            # 转换为 StreamResult
            return StreamResult(
                repo_path=repo_path,
                status="success" if execution_result.success else "failed",
                output=execution_result.stdout,
                error=execution_result.stderr,
                metadata={
                    'execution_time': execution_result.execution_time,
                    'retries': execution_result.retries
                }
            )
            
        except Exception as e:
            return StreamResult(
                repo_path=repo_path,
                status="failed",
                error=str(e)
            )
    
    def _on_result(self, result: StreamResult):
        """单个结果回调"""
        self.reporter.log_result(
            result.repo_path,
            result.status,
            result.output,
            result.error
        )
    
    def _on_batch(self, batch: List[StreamResult]):
        """批处理回调"""
        # 可以在这里实现批处理逻辑
        pass
    
    def _on_error(self, result: StreamResult):
        """错误回调"""
        if self.config.verbose:
            print(f"错误: {result.repo_path} - {result.error}")
    
    def _generate_report(self):
        """生成报告"""
        # 打印汇总报告
        self.reporter.print_summary()
        
        # 如果有流式处理器，导出详细结果
        if self.stream_processor:
            # 导出 JSON 报告
            json_report = self.stream_processor.export_results('json')
            report_file = f"git_pull_report_{int(time.time())}.json"
            
            with open(report_file, 'w', encoding='utf-8') as f:
                f.write(json_report)
            
            print(f"详细报告已保存到: {report_file}")
    
    def _print_performance_stats(self):
        """打印性能统计"""
        total_time = self.end_time - self.start_time
        
        print("\n" + "="*50)
        print("性能统计")
        print("="*50)
        print(f"总执行时间: {total_time:.2f}秒")
        
        # 扫描器统计
        if self.scanner:
            scanner_stats = self.scanner.get_stats()
            print(f"\n目录扫描:")
            print(f"  - 扫描时间: {scanner_stats['scan_time']:.2f}秒")
            print(f"  - 找到仓库: {scanner_stats['git_repos_found']}")
            print(f"  - 缓存命中: {scanner_stats['cache_hits']}")
        
        # 执行器统计
        if self.executor:
            executor_stats = self.executor.get_stats()
            print(f"\nGit 执行:")
            print(f"  - 总命令数: {executor_stats['total_commands']}")
            print(f"  - 成功命令: {executor_stats['successful_commands']}")
            print(f"  - 失败命令: {executor_stats['failed_commands']}")
            print(f"  - 总重试次数: {executor_stats['total_retries']}")
            print(f"  - 平均执行时间: {executor_stats['average_time']:.2f}秒")
        
        # 线程池统计
        if self.pool_manager:
            pool_stats = self.pool_manager.get_stats()
            print(f"\n线程池:")
            print(f"  - 提交任务: {pool_stats['submitted']}")
            print(f"  - 完成任务: {pool_stats['completed']}")
            print(f"  - 失败任务: {pool_stats['failed']}")
        
        # 系统资源
        process = psutil.Process()
        memory_info = process.memory_info()
        print(f"\n系统资源:")
        print(f"  - 内存使用: {memory_info.rss / 1024 / 1024:.1f} MB")
        print(f"  - CPU 使用率: {process.cpu_percent()}%")
        
        print("="*50)
    
    def cleanup(self):
        """清理资源"""
        try:
            # 停止流式处理器
            if self.stream_processor:
                self.stream_processor.stop()
            
            # 停止线程池
            if self.pool_manager:
                self.pool_manager.stop()
            
        except Exception as e:
            print(f"清理资源时出错: {e}")


def parse_arguments():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(
        description="Git Pull All - 批量 Git 仓库更新工具（优化版）",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  %(prog)s --directory /path/to/projects --verbose
  %(prog)s -d . --include "*project*" --exclude "*test*"
  %(prog)s --dry-run --timeout 600 --max-workers 8
        """
    )
    
    parser.add_argument(
        '-d', '--directory',
        default='.',
        help='要扫描的根目录（默认: 当前目录）'
    )
    
    parser.add_argument(
        '--include',
        nargs='*',
        default=[],
        help='包含模式列表（只处理匹配的仓库）'
    )
    
    parser.add_argument(
        '--exclude',
        nargs='*',
        default=['*/.git', '*/venv', '*/node_modules', '*/temp'],
        help='排除模式列表（默认: %(default)s）'
    )
    
    parser.add_argument(
        '-v', '--verbose',
        action='store_true',
        help='启用详细输出'
    )
    
    parser.add_argument(
        '--dry-run',
        action='store_true',
        help='预览模式，不实际执行 git pull'
    )
    
    parser.add_argument(
        '--timeout',
        type=int,
        default=300,
        help='Git 命令超时时间（秒，默认: %(default)s）'
    )
    
    parser.add_argument(
        '--max-workers',
        type=int,
        default=4,
        help='最大工作线程数（默认: %(default)s）'
    )
    
    parser.add_argument(
        '--version',
        action='version',
        version='%(prog)s 2.0 (优化版)'
    )
    
    return parser.parse_args()


def main():
    """主函数"""
    # 解析命令行参数
    args = parse_arguments()
    
    # 创建并运行优化版本的工具
    app = OptimizedGitPullAll()
    return_code = app.run(args)
    
    sys.exit(return_code)


if __name__ == "__main__":
    main()